/**
 * @brief Frame缓存单件类，注意 ,该类的使用与业务有关，就是需要根据通道编号以及设备编号来检索缓存。
* date:2023/12/18 
 * author:Coolio
 */

#ifndef ZMEDIASERVER_SRC_COMMON_MEDIASOURCECACHECENTER_H
#define ZMEDIASERVER_SRC_COMMON_MEDIASOURCECACHECENTER_H

#ifdef ENABLE_CACHE

#include <memory>
#include <atomic>
#include "Poller/Timer.h"
#include "Cache/DeviceRecordCache.h"
#include "Cache/PrivateProtocol.h"
#include "Common/MediaSource.h"
using namespace toolkit;

namespace mediakit{
    
    class DeviceRecordCacheHelper : public SerializeObject, public std::enable_shared_from_this<DeviceRecordCacheHelper> {
        public:
            typedef std::shared_ptr<DeviceRecordCacheHelper> Ptr;
            DeviceRecordCacheHelper(const privateproto::DeviceChannel& dev_chan, bool autoscribe = false);
            ~DeviceRecordCacheHelper();
            DeviceRecordCache::Ptr & getCacher();
            /**
             * 清理缓存
             * @return >= 0 -  已经清理的内存大小,保留缓存对象, < 0 - 删除对象对象，再取负值就是清理的内存大小
             */
            int64_t PurgeMemory(const int machine_memory,const int process_memory);
            
            int64_t DeviceCacheMemorySize();
            /**
             * 删除缓存
             */
            void CleanCache();
        public:
            //// SerializeObject override ////
            Value DumpAsJson() override;
            void DumpAsJsonInfo(const function<void(const Json::Value& info)> &cb);
        private:
            DeviceRecordCache::Ptr m_cache_reord;
            privateproto::DeviceChannel m_dev_chan;
    };

    class MediaSourceCacheCenter : public std::enable_shared_from_this<MediaSourceCacheCenter> {
        public:
            typedef std::shared_ptr<MediaSourceCacheCenter> Ptr;
            MediaSourceCacheCenter();
            ~MediaSourceCacheCenter();
            /**
            * 获取一个缓存处理器
            * @param stream_id 流id
            * @param autoscribe 自动创建订阅者,使能回放流走缓存
            * @return DeviceRecordCache::Ptr
            */
            DeviceRecordCache::Ptr GetRecordCacher(const privateproto::DeviceChannel& dev_chan,bool bcreate = true, bool autoscribe = false);
            
            static MediaSourceCacheCenter &Instance();
            /**
             * 检查内存是否已经超了
             */
            bool CheckMemReachLimit() const;
        public:
            void DumpAsJsonInfo(const std::string & channel_id,const function<void(const Json::Value& info)> &cb);
        private:
            Timer::Ptr                      m_check_timer;
            //本socket绑定的poller线程，事件触发于此线程
            EventPoller::Ptr                m_poller;
            recursive_mutex                 m_mtx_map;
            std::atomic<bool>               m_bmemreachLimit = {false};//内存是否占用超过安全阈值而被禁用缓存功能
            std::map<privateproto::DeviceChannel,DeviceRecordCacheHelper::Ptr> m_map_cache_reord;
            static const int                m_machine_memory;
    };
}
#endif
#endif
